﻿using System.Linq.Expressions;

using Tszy.Unlimited.Data.AdoNet.Sql.Providers;

namespace Tszy.Unlimited.Data.AdoNet.Sql.Components.Db.Mysql
{
    /// <summary>
    ///
    /// </summary>
    /// <typeparam name="TSource"></typeparam>
    /// <typeparam name="TResult"></typeparam>
    public class ExecuteQuery<TSource, TResult> : ExecuteQueryBase<TSource, TResult>
        where TSource : new()
    {
        private readonly IDataProvider _dataProvider;

        /// <summary>
        /// 是否显示 SQL。
        /// </summary>
        private bool _showSql = false;

        /// <summary>
        /// 输出 SQL 方法。
        /// </summary>
        private Action<string> _printSql = null;

        /// <summary>
        /// 初始化。
        /// </summary>
        /// <param name="query">查询对象。</param>
        /// <param name="dataProvider">数据提供者。</param>
        /// <param name="showSql"></param>
        /// <param name="printSql"></param>
        public ExecuteQuery(IQuery<TSource> query, IDataProvider dataProvider, bool showSql = false, Action<string> printSql = null) : base(query)
        {
            _dataProvider = dataProvider;

            _showSql = showSql;
            _printSql = printSql;
        }

        /// <summary>
        ///
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public override T Execute<T>()
        {
            var sql = SqlBuilder.BuildSelect("", _query.Context, _showSql, _printSql);

            return _dataProvider.Field<T>(sql, _query.Context.ParameterValues);
        }

        /// <summary>
        ///
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public override async Task<T> ExecuteAsync<T>()
        {
            var sql = SqlBuilder.BuildSelect("", _query.Context, _showSql, _printSql);

            return await _dataProvider.FieldAsync<T>(sql, _query.Context.ParameterValues);
        }

        /// <summary>
        ///
        /// </summary>
        /// <param name="predicate"></param>
        /// <returns></returns>
        public override TResult FirstOrDefault(Expression<Func<TResult, bool>> predicate)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        ///
        /// </summary>
        /// <param name="predicate"></param>
        /// <returns></returns>
        public override Task<TResult> FirstOrDefaultAsync(Expression<Func<TResult, bool>> predicate)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        ///
        /// </summary>
        /// <returns></returns>
        public override QueryEnumerableResult<TResult> ToEnumerable()
        {
            var sql = SqlBuilder.BuildSelect("", _query.Context, _showSql, _printSql);

            var result = new QueryEnumerableResult<TResult> { SQL = sql };

            result.Status = true;
            result.List = _dataProvider.Query<TResult>(sql, _query.Context.ParameterValues) ?? new List<TResult>();

            return result;
        }

        /// <summary>
        ///
        /// </summary>
        /// <returns></returns>
        public override async Task<QueryEnumerableResult<TResult>> ToEnumerableAsync()
        {
            var sql = SqlBuilder.BuildSelect("", _query.Context, _showSql, _printSql);

            var result = new QueryEnumerableResult<TResult> { SQL = sql };

            result.Status = true;
            result.List = await _dataProvider.QueryAsync<TResult>(sql, _query.Context.ParameterValues) ?? new List<TResult>();

            return result;
        }
    }
}